﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

using BizElements.Generator.Properties;

namespace BizElements.Generator
{
    public enum BizElementsSettingsType
    {
        OrmProject,
        DotNetProject
    }

    public sealed class BizElementsSettings
    {
        const string BizElements = "BizElements";
        const string Setting = "Setting";
        const string Key = "Key";
        const string Value = "Value";

        #region Fields.

        SortedList<string, string> settings = new SortedList<string, string>();

        #endregion

        #region CTor.

        private BizElementsSettings()
        {
        }

        public BizElementsSettings(BizElementsSettingsType settingsType)
        {
            this.SettingsType = settingsType;
            this.HasChanges = false;
        }

        #endregion

        #region Indexer.

        public string this[string key]
        {
            get
            {
                string value;
                this.settings.TryGetValue(key, out value);
                return value;
            }
            set
            {
                bool hasChanged = (value != this[key]);
                if (hasChanged)
                {
                    this.settings[key] = value;
                    this.HasChanges = true;
                }
            }
        }

        #endregion

        #region SettingsType property.

        private const string SettingsTypeKey = "__SettingsType";

        public BizElementsSettingsType SettingsType
        {
            get 
            {
                string cfgValue = this[SettingsTypeKey] ?? BizElementsSettingsType.OrmProject.ToString();
                return (BizElementsSettingsType)Enum.Parse(typeof(BizElementsSettingsType), cfgValue);
            }
            private set { this[SettingsTypeKey] = value.ToString(); }
        }

        #endregion

        #region Load.

        public static BizElementsSettings LoadFromFile(string filePath)
        {
            DataSet ds = new DataSet(BizElements);
            ds.ReadXml(filePath);
            if (!HasValidStructure(ds))
                throw new Exception(Messages.BizElementsSettings_InvalidXmlStructure);

            BizElementsSettings settings = new BizElementsSettings();
            foreach (DataRow row in ds.Tables[Setting].Rows)
            {
                string key = Convert.ToString(row[Key]);
                string value = Convert.ToString(row[Value]);
                settings[key] = value;
            }

            settings.HasChanges = false;
            return settings;
        }

        private static bool HasValidStructure(DataSet ds)
        {
            bool hasValidStructure = ds.Tables.Contains(Setting) && ds.Tables[Setting].Columns.Contains(Key) && ds.Tables[Setting].Columns.Contains(Value);
            return hasValidStructure;
        }

        #endregion

        #region Save.

        public void SaveToFile(string filePath)
        {
            DataSet ds = new DataSet(BizElements);
            DataTable tbl = ds.Tables.Add(Setting);
            var key = tbl.Columns.Add(Key, typeof(string));
            tbl.Columns.Add(Value, typeof(string));
            foreach (KeyValuePair<string, string> keyAndVal in this.settings)
                tbl.Rows.Add(keyAndVal.Key, keyAndVal.Value);

            ds.WriteXml(filePath, XmlWriteMode.IgnoreSchema);
            this.HasChanges = false;
        }

        #endregion

        public bool HasChanges { get; private set; }

        public void Clear()
        {
            var settingsType = this.SettingsType;
            this.settings.Clear();
            this.SettingsType = settingsType;
        }
    }
}
